<template>
  <div class="crop-container" ref="container">
    <div class="crop-box" :style="boxStyle" @mousedown="startMove">
      <div class="rotation-handle" @mousedown.stop="startRotate"></div>
      <div
        v-for="handle in handles"
        :key="handle.position"
        class="crop-handle"
        :class="`handle-${handle.position}`"
        :style="getHandleStyle(handle.position)"
        @mousedown.stop="startResize(handle.position, $event)"
      ></div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from "vue";

const props = defineProps({
  modelValue: {
    type: Object,
    required: true
  },
  minWidth: {
    type: Number,
    default: 50
  },
  minHeight: {
    type: Number,
    default: 50
  }
});

const emit = defineEmits(["update:modelValue"]);

const container = ref(null);
const isDragging = ref(false);
const isResizing = ref(false);
const isRotating = ref(false);
const resizeDirection = ref(""); // 新增方向状态
const startPos = ref({ x: 0, y: 0 });
const startBox = ref({});

// 手柄配置
const handles = [
  { position: "top" },
  { position: "bottom" },
  { position: "left" },
  { position: "right" },
  { position: "top-left" },
  { position: "top-right" },
  { position: "bottom-left" },
  { position: "bottom-right" }
];

const boxStyle = computed(() => ({
  left: `${props.modelValue.x}px`,
  top: `${props.modelValue.y}px`,
  width: `${props.modelValue.width}px`,
  height: `${props.modelValue.height}px`,
  transform: `rotate(${props.modelValue.rotate}deg)`,
  transformOrigin: "center center",
  background: "rgba(0, 0, 0, 0.5)"
}));

// 旋转处理
function startRotate(e) {
  isRotating.value = true;
  const rect = container.value.getBoundingClientRect();
  const center = {
    x: props.modelValue.x + props.modelValue.width / 2,
    y: props.modelValue.y + props.modelValue.height / 2
  };
  startPos.value = {
    x: e.clientX - rect.left,
    y: e.clientY - rect.top,
    center
  };
  document.addEventListener("mousemove", handleRotate);
  document.addEventListener("mouseup", stopRotate);
}

function handleRotate(e) {
  if (!isRotating.value) return;

  const rect = container.value.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;

  const angle =
    (Math.atan2(
      mouseY - startPos.value.center.y,
      mouseX - startPos.value.center.x
    ) *
      180) /
      Math.PI +
    90;

  emit("update:modelValue", {
    ...props.modelValue,
    rotate: angle % 360
  });
}

function stopRotate() {
  isRotating.value = false;
  document.removeEventListener("mousemove", handleRotate);
  document.removeEventListener("mouseup", stopRotate);
}

// 坐标转换函数
function rotatePoint(x, y, angle, cx, cy) {
  const radians = (angle * Math.PI) / 180;
  return {
    x: (x - cx) * Math.cos(radians) - (y - cy) * Math.sin(radians) + cx,
    y: (x - cx) * Math.sin(radians) + (y - cy) * Math.cos(radians) + cy
  };
}

function startResize(position, e) {
  isResizing.value = true;
  resizeDirection.value = position; // 设置当前调整方向
  startPos.value = { x: e.clientX, y: e.clientY };
  startBox.value = { ...props.modelValue };

  // 坐标转换逻辑...
  const rect = container.value.getBoundingClientRect();
  const center = {
    x: startBox.value.x + startBox.value.width / 2,
    y: startBox.value.y + startBox.value.height / 2
  };
  const rotatedPoint = rotatePoint(
    e.clientX - rect.left,
    e.clientY - rect.top,
    -startBox.value.rotate,
    center.x,
    center.y
  );

  startPos.value.rotatedX = rotatedPoint.x;
  startPos.value.rotatedY = rotatedPoint.y;

  document.addEventListener("mousemove", handleResize);
  document.addEventListener("mouseup", stopResize);
}

function handleResize(e) {
  if (!isResizing.value) return;

  const rect = container.value.getBoundingClientRect();
  const mouseX = e.clientX - rect.left;
  const mouseY = e.clientY - rect.top;

  // 转换到旋转前坐标系
  const center = {
    x: startBox.value.x + startBox.value.width / 2,
    y: startBox.value.y + startBox.value.height / 2
  };
  const rotatedPoint = rotatePoint(
    mouseX,
    mouseY,
    -startBox.value.rotate,
    center.x,
    center.y
  );

  const dx = rotatedPoint.x - startPos.value.rotatedX;
  const dy = rotatedPoint.y - startPos.value.rotatedY;

  const newBox = { ...startBox.value };
  const ratio = startBox.value.width / startBox.value.height;

  switch (resizeDirection.value) {
    case "top":
      newBox.height = Math.max(props.minHeight, startBox.value.height - dy);
      newBox.y = startBox.value.y + (startBox.value.height - newBox.height);
      break;
    case "bottom":
      newBox.height = Math.max(props.minHeight, startBox.value.height + dy);
      break;
    case "left":
      newBox.width = Math.max(props.minWidth, startBox.value.width - dx);
      newBox.x = startBox.value.x + (startBox.value.width - newBox.width);
      break;
    case "right":
      newBox.width = Math.max(props.minWidth, startBox.value.width + dx);
      break;
    case "top-left":
      newBox.width = Math.max(props.minWidth, startBox.value.width - dx);
      newBox.height = Math.max(props.minHeight, newBox.width / ratio);
      newBox.x = startBox.value.x + (startBox.value.width - newBox.width);
      newBox.y = startBox.value.y + (startBox.value.height - newBox.height);
      break;
    case "top-right":
      newBox.width = Math.max(props.minWidth, startBox.value.width + dx);
      newBox.height = Math.max(props.minHeight, newBox.width / ratio);
      newBox.y = startBox.value.y + (startBox.value.height - newBox.height);
      break;
    case "bottom-left":
      newBox.width = Math.max(props.minWidth, startBox.value.width - dx);
      newBox.height = Math.max(props.minHeight, newBox.width / ratio);
      newBox.x = startBox.value.x + (startBox.value.width - newBox.width);
      break;
    case "bottom-right":
      newBox.width = Math.max(props.minWidth, startBox.value.width + dx);
      newBox.height = Math.max(props.minHeight, newBox.width / ratio);
      break;
  }

  // 边界约束
  newBox.x = Math.max(
    0,
    Math.min(newBox.x, container.value.offsetWidth - newBox.width)
  );
  newBox.y = Math.max(
    0,
    Math.min(newBox.y, container.value.offsetHeight - newBox.height)
  );

  emit("update:modelValue", newBox);
}

// 手柄位置计算
function getHandleStyle(position) {
  const angle = props.modelValue.rotate;
  const style = {};

  switch (position) {
    case "top":
      style.top = "-6px";
      style.left = "50%";
      style.transform = `translateX(-50%) rotate(${-angle}deg)`;
      break;
    case "bottom":
      style.bottom = "-6px";
      style.left = "50%";
      style.transform = `translateX(-50%) rotate(${-angle}deg)`;
      break;
    case "left":
      style.left = "-6px";
      style.top = "50%";
      style.transform = `translateY(-50%) rotate(${-angle}deg)`;
      break;
    case "right":
      style.right = "-6px";
      style.top = "50%";
      style.transform = `translateY(-50%) rotate(${-angle}deg)`;
      break;
    // 对角手柄保持原有位置
    default:
      style[position.split("-")[0]] = "-6px";
      style[position.split("-")[1]] = "-6px";
      style.transform = `rotate(${-angle}deg)`;
  }
  return style;
}
</script>

<style>
.rotation-handle {
  position: absolute;
  top: -40px;
  left: 50%;
  width: 20px;
  height: 20px;
  background: #fff;
  border-radius: 50%;
  transform: translateX(-50%);
  cursor: grab;
}

/* 保持手柄方向始终可见 */
.crop-handle {
  position: absolute;
  width: 12px;
  height: 12px;
  background: #fff;
  border: 1px solid #333;
  transform-origin: center;
}

.handle-top-left {
  cursor: nwse-resize;
}
.handle-top-right {
  cursor: nesw-resize;
}
.handle-bottom-left {
  cursor: nesw-resize;
}
.handle-bottom-right {
  cursor: nwse-resize;
}
.handle-top,
.handle-bottom {
  cursor: ns-resize;
}
.handle-left,
.handle-right {
  cursor: ew-resize;
}
</style>
